package de.johanngehrisch.pacecalc.android.activities;

import de.johanngehrisch.pacecalc.android.R;
import de.johanngehrisch.pacecalc.model.PaceCalculator;
import de.johanngehrisch.pacecalc.model.PaceCalculator.CalcMode;
import de.johanngehrisch.pacecalc.model.PaceCalculator.PaceUnit;
import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;

public class PaceCalcActivity extends Activity {

	Spinner calcmode;
	EditText distance;
	Spinner distanceUnit;
	EditText duration;
	EditText pace;
	Spinner paceUnit;
	int currentDistanceUnit;
	int currentPaceUnit;

	private static final String distanceFormat = "%.2f";
	private static final String timeFormat = "%02d:%02d:%02d";

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.pacecalc);

		calcmode = (Spinner) findViewById(R.id.pacecalc_calcmode);
		distance = (EditText) findViewById(R.id.pacecalc_distance);
		distanceUnit = (Spinner) findViewById(R.id.pacecalc_distanceunit);
		duration = (EditText) findViewById(R.id.pacecalc_duration);
		pace = (EditText) findViewById(R.id.pacecalc_pace);
		paceUnit = (Spinner) findViewById(R.id.pacecalc_paceunit);

		// Configure options for spinners
		calcmode.setAdapter(ArrayAdapter.createFromResource(this,
				R.array.pacecalc_calcmodes,
				android.R.layout.simple_spinner_item));
		distanceUnit.setAdapter(ArrayAdapter.createFromResource(this,
				R.array.pacecalc_distanceunit,
				android.R.layout.simple_spinner_item));
		paceUnit.setAdapter(ArrayAdapter
				.createFromResource(this, R.array.pacecalc_paceunit,
						android.R.layout.simple_spinner_item));

		// Add Listeners to spinners
		calcmode.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				updateFieldVisibility();
			}

			public void onNothingSelected(AdapterView<?> arg0) {
			}

		});

		distance.addTextChangedListener(new TextWatcher() {

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
			}

			public void afterTextChanged(Editable s) {
				if (distance.isEnabled()) {
					updateFieldValues();
				}
			}
		});

		distanceUnit.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {

				int oldDistanceUnit = currentDistanceUnit;
				currentDistanceUnit = distanceUnit
				.getSelectedItemPosition();
				
				if (currentDistanceUnit != oldDistanceUnit) {
					distance.setText(String.format(distanceFormat, PaceCalculator
							.convertDistance(Float.parseFloat(distance
									.getText().toString()),
									oldDistanceUnit, currentDistanceUnit)));
				}
			}

			public void onNothingSelected(AdapterView<?> arg0) {
			}

		});

		duration.addTextChangedListener(new TextWatcher() {

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
			}

			public void afterTextChanged(Editable s) {
				if (duration.isEnabled()) {
					updateFieldValues();
				}
			}
		});

		pace.addTextChangedListener(new TextWatcher() {

			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
			}

			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {

			}

			public void afterTextChanged(Editable s) {
				if (pace.isEnabled()) {
					updateFieldValues();
				}
			}
		});

		paceUnit.setOnItemSelectedListener(new OnItemSelectedListener() {

			public void onItemSelected(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {

				int oldPaceUnit = currentPaceUnit;
				currentPaceUnit = paceUnit
				.getSelectedItemPosition();
				
				if (currentPaceUnit != oldPaceUnit) {
					pace.setText(paceFromFloat(PaceCalculator
							.convertPace(paceToFloat(pace
									.getText().toString(), oldPaceUnit),
									oldPaceUnit, currentPaceUnit), currentPaceUnit));
				}
			}

			public void onNothingSelected(AdapterView<?> arg0) {
			}

		});

		currentDistanceUnit = distanceUnit.getSelectedItemPosition();
		currentPaceUnit = paceUnit.getSelectedItemPosition();
	}

	private void updateFieldVisibility() {

		switch (calcmode.getSelectedItemPosition()) {
		case CalcMode.distance:
			distance.setEnabled(false);
			duration.setEnabled(true);
			pace.setEnabled(true);
			break;

		case CalcMode.duration:
			distance.setEnabled(true);
			duration.setEnabled(false);
			pace.setEnabled(true);
			break;

		case CalcMode.pace:
			distance.setEnabled(true);
			duration.setEnabled(true);
			pace.setEnabled(false);
			break;
		}

	}


	private void updateFieldValues() {

		int selectedCalcMode = calcmode.getSelectedItemPosition();

		switch (selectedCalcMode) {
		case CalcMode.distance:
			if (duration.getText().length() > 0 && pace.getText().length() > 0) {
				float durationSec = timeToSeconds(duration.getText().toString());
				float paceSec = paceToFloat(pace.getText().toString(), currentPaceUnit);

				distance.setText(String.format(distanceFormat, PaceCalculator
						.calculatePace(selectedCalcMode, durationSec, paceSec,
								currentDistanceUnit, currentPaceUnit)));
			} else {
				distance.setText("");
			}
			break;

		case CalcMode.duration:
			if (distance.getText().length() > 0 && pace.getText().length() > 0) {
				float paceSec = paceToFloat(pace.getText().toString(), currentPaceUnit);

				duration.setText(timeFromSeconds((int) PaceCalculator
						.calculatePace(selectedCalcMode, new Float(distance
								.getText().toString()), paceSec,
								currentDistanceUnit, currentPaceUnit)));
			} else {
				duration.setText("");
			}
			break;

		case CalcMode.pace:
			if (distance.getText().length() > 0
					&& duration.getText().length() > 0) {
				float durationSec = timeToSeconds(duration.getText().toString());

				pace.setText(paceFromFloat(PaceCalculator
							.calculatePace(selectedCalcMode, new Float(distance
									.getText().toString()), durationSec,
									currentDistanceUnit, currentPaceUnit), currentPaceUnit));
			} else {
				pace.setText("");
			}
			break;
		}

	}

	private float timeToSeconds(String time) {
		int timeAsSeconds = 0;

		String[] timeArray = time.split(":");
		for (int i = 0; i < timeArray.length; i++) {
			try {
			timeAsSeconds += Math.pow(60, timeArray.length - i - 1)
					* Integer.parseInt(timeArray[i]);
			} catch(NumberFormatException e) {
				e.printStackTrace();
				return 0;
			}

		}

		return timeAsSeconds;
	}

	private String timeFromSeconds(int timeAsSeconds) {
		int hours = (int) Math.floor(timeAsSeconds / 3600);
		int minutes = (int) Math.floor((timeAsSeconds - hours * 3600) / 60);
		int seconds = timeAsSeconds - hours * 3600 - minutes * 60;

		return String.format(timeFormat, hours, minutes, seconds);
	}
	
	private float paceToFloat(String paceAsString, int paceUnit) {
		if(paceUnit == PaceUnit.minutesPerKilometer || paceUnit == PaceUnit.minutesPerMile) 
			return timeToSeconds(pace.getText().toString());
		else {
			return Float.parseFloat(pace.getText().toString());
		}
	}
	
	private String paceFromFloat(float paceAsFloat, int paceUnit) {
		if(paceUnit == PaceUnit.minutesPerKilometer || paceUnit == PaceUnit.minutesPerMile)
			return timeFromSeconds((int) paceAsFloat);
		else
			return String.format(distanceFormat, paceAsFloat);
	}
}
